package com.jc.platform.coursemanage.service.base.impl;

import com.jc.platform.coursemanage.mapper.ICourseMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;




import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jc.platform.common.annotation.DataIsolation;
import com.jc.platform.common.constants.GlobalConstant;
import com.jc.platform.common.constants.StringPool;
import com.jc.platform.common.model.UserInfo;
import com.jc.platform.common.model.QueryParam;
import com.jc.platform.common.result.PageInfo;
import com.jc.platform.common.result.ResultCodeEnum;
import com.jc.platform.common.result.ResultModel;
import com.jc.platform.common.search.SqlUtils;
import com.jc.platform.common.utils.BeanUtil;
import com.jc.platform.common.utils.RequestUtil;
import com.jc.platform.coursemanage.vo.CourseVO;
import com.jc.platform.coursemanage.entity.CourseEntity;
import com.jc.platform.coursemanage.mapper.ICourseMapper;
import com.jc.platform.coursemanage.service.base.impl.BaseServiceImpl;
import com.jc.platform.coursemanage.service.base.IBaseCourseService;
import com.jc.platform.mybatis.utils.CollectCovertUtil;
import com.jc.platform.mybatis.utils.ConditionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import com.jc.platform.coursemanage.vo.EnrollCourseVO;
import com.jc.platform.coursemanage.service.IEnrollCourseService;
import com.jc.platform.coursemanage.vo.RequiredCourseVO;
import com.jc.platform.coursemanage.service.IRequiredCourseService;

import com.jc.platform.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.jc.platform.common.utils.CollectionUtil;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * ClassName AbstractCourseServiceImpl.java
 * Description 
 *
 * @author Wen
 * @version 7.0
 * @date 2021/09/28
 */
@Slf4j
public abstract class AbstractCourseServiceImpl extends BaseServiceImpl<CourseVO> implements IBaseCourseService
{
	private static final String KEY_PREFIX = "db_platformCoursemanage:t_course";

    @Autowired
    private RedisUtils<String, CourseVO> redisUtils;
    @Autowired
    private IEnrollCourseService enrollCourseService;
    @Autowired
    private IRequiredCourseService requiredCourseService;
    @Autowired
    private ICourseMapper courseMapper;



	@Override
	public ResultModel<CourseVO> insert(CourseVO courseVO)
	{
		CourseEntity entity = new CourseEntity();
		entity.copyFormVO(courseVO);
		courseMapper.insert(entity);

		courseVO.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
		return ResultModel.success(courseVO);
	}

	@Override
	public ResultModel<CourseVO> update(CourseVO course)
	{
		CourseEntity entity = new CourseEntity();
		entity.copyFormVO(course);
		courseMapper.updateById(entity);



		course.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
        delFromRedisAsync(entity.getId());
		entity = courseMapper.selectById(entity.getId());
		return ResultModel.success(entity.copyToVO());
	}

    @Override
	public ResultModel<Boolean> delete(Long id)
	{
        if (!delCheck(id)) {
            return ResultModel.failed(ResultCodeEnum.REQUEST_PARAMS_ERROR.code(), "该条数据被其他数据关联");
        }
        
         int count = courseMapper.deleteById(id);

		if (count > 0)
		{
			delRedisKeyBatch(KEY_PREFIX);
            delFromRedisAsync(id);
			return ResultModel.success(true);
		}
		else
		{
			return ResultModel.success(false);
		}
	}

    @Override
	public ResultModel<Boolean> deleteBatch(List<Long> ids)
	{
        if (CollectionUtil.isEmpty(ids)) {
			return ResultModel.success(true);
		}
        ids.forEach(id -> {
                if (!delCheck(id)) {
                    return;
                }
            courseMapper.deleteById(id);
        });

        delRedisKeyBatch(KEY_PREFIX);
        return ResultModel.success(true);
	}

    private boolean delCheck(Long id){
        QueryParam queryParam = new QueryParam();
        queryParam.setSortBy("id");
        String q;
        q = "course_id=" + id;
        queryParam.setQ(q);
        if (enrollCourseService.count(queryParam).getData() != 0) { 
            return false;
        } 
        q = "course_id=" + id;
        queryParam.setQ(q);
        if (requiredCourseService.count(queryParam).getData() != 0) { 
            return false;
        } 
        return true;
    }



	@Override
	public Boolean checkNotExists(Long id, String property, String value)
	{
        QueryWrapper<CourseEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(BeanUtil.newInstance(CourseEntity.class));
        queryWrapper.eq(SqlUtils.getColumnByProperty(property), value);

        if(id!=null && id>0){
            queryWrapper.ne(StringPool.ID, id);
        }


        return courseMapper.selectCount(queryWrapper) <= 0;
	}

	@Override
	public ResultModel<CourseVO> get(Long id)
	{
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, id);
        CourseVO courseVO = getRedis(redisKey);
        if (courseVO == null)
        {
            CourseEntity entity = courseMapper.selectById(id);
            if (entity == null){
                return ResultModel.failed();
            }
            courseVO = entity.copyToVO();


            setRedis(redisKey, courseVO);
        }
        return ResultModel.success(courseVO);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<List<CourseVO>> find(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:find." + queryParam.toString());
        List<CourseVO> list = getRedisForList(redisKey);
            if (list == null || list.isEmpty())
            {
                QueryWrapper<CourseEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, CourseEntity.class);
                List<CourseEntity> entities = courseMapper.selectList(queryWrapper);
                list = CollectCovertUtil.listVO(entities);

                if (list != null && !list.isEmpty())
                {
                    setRedis(redisKey,list);
                }
            }
        return ResultModel.success(list);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<PageInfo<CourseVO>> finds(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());

        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:finds." + queryParam.toString());
        PageInfo<CourseVO> page = getRedisForPage(redisKey);
        if (page == null)
        {
            QueryWrapper<CourseEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, CourseEntity.class);
            IPage<CourseEntity> entityPage = courseMapper.selectPage(ConditionUtil.getPage(queryParam), queryWrapper);
            page = CollectCovertUtil.pageVO(entityPage);


            setRedis(redisKey,page);
        }
        return ResultModel.success(page);

	}

    @Override
	public ResultModel<Integer> count(QueryParam queryParam)
	{
        QueryWrapper<CourseEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, CourseEntity.class);
        Integer count = courseMapper.selectCount(queryWrapper);
		return ResultModel.success(count);
	}



	@Override
	public ResultModel<List<CourseVO>> importData(List<CourseVO> courseList) {
		List<CourseEntity> saves = new ArrayList<>();
		List<CourseVO> returnList = new ArrayList<>();
		for (CourseVO course : courseList) {
			CourseEntity entity = new CourseEntity();
			entity.copyFormVO(course);
			saves.add(entity);
		}
		saves.forEach(entity -> {
			courseMapper.insert(entity);
			CourseVO course = entity.copyToVO();
			returnList.add(course);
		});
		return ResultModel.success(courseList);
	}




    private void delFromRedisAsync(Object id)
	{
		CompletableFuture.runAsync(() -> {
			try
			{
				TimeUnit.SECONDS.sleep(1);
				redisUtils.del(RedisUtils.getRedisKey(KEY_PREFIX, id));
			}
			catch (InterruptedException e)
			{
				log.error("缓存删除线程错误", e);
				Thread.currentThread()
					  .interrupt();
			}
		});
	}

	private void delColRedis()
	{
		String keyPattern = RedisUtils.getRedisKey(KEY_PREFIX, "collection:*");
		Set<String> keys = redisUtils.keys(keyPattern);
		if (keys != null)
		{
			String[] keyArray = keys.toArray(new String[] {});
			redisUtils.del(keyArray);
		}
	}
}

